﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using AgFx;
using Coding4Fun.Phone.Controls.Data;
using DepSoft.Mobile.WP7.FollwIt.Framework;
using DepSoft.Mobile.WP7.FollwIt.Messages;
using DepSoft.Mobile.WP7.FollwIt.Model;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Microsoft.Phone.Controls;
using WP7Contrib.Services.Navigation;
using WP7Contrib.Services.Settings;
using WP7Contrib.Services.Storage;

namespace DepSoft.Mobile.WP7.FollwIt.ViewModel
{
    /// <summary>
    /// Coding
    /// TODO: Add assync check on ProgressBar overlay, for the 2 requests ( Movies & TVShows )!
    /// TODO: Loading up the movies and tv shows through AGFX needs rework so that they are ObservableCollections binded to the Views!
    /// -> Currently paged : Add paged movie collection: http://indyfromoz.wordpress.com/2010/08/30/windows-phone-7-listbox-pagination-with-mvvmlight-applicationbar/
    /// TODO: Need to store the password credentials on secure way http://robtiffany.com/windows-phone/encrypting-your-credentials-on-windows-phone-7-5
    /// TODO: Move account credentials to a settings page
    /// 
    /// Suggestions
    /// TODO: Ancestor binding: http://blog.thekieners.com/2010/09/08/relativesource-binding-with-findancestor-mode-in-silverlight/
    /// TODO: Design: http://www.istartedsomething.com/20100815/conceptual-usga-golf-scoring-app-microsoft-windows-phone-7-apps-done-right/
    /// TODO: Other Page transitions: http://blogs.xamlninja.com/blend/wp7contrib-page-transitions-and-navigation-service
    /// TODO: Good example! http://wmpoweruser.com/introducing-better-movie-manager
    /// </summary>
    public class MainViewModel : ViewModelBaseWp7
    {
        #region Private members
        enum SelectedItem
        {
            Movie,
            TVShow
        }

        enum PageMode
        {
            First,
            Previous,
            Next
        }

        enum PivotName
        {
            MenuPivotItem,
            MoviePivotItem,
            TVShowPivotItem,
            StreamPivotItem,
            SettingsPivotItem
        }

        private agfxMovieCollectionViewModel _movieCollectionVM;
        private agfxTVShowCollectionViewModel _tvShowCollectionVM;

        private int _currentPageMovie = 0;
        private int _currentPageTVShow = 0;
        private int _pageSize = 9; //18;
        private PivotName _currentPivot = PivotName.MoviePivotItem;

        private int _friendsCount = 0;
        #endregion

        #region Public properties
        public string MenuPageName { get { return "menu"; } }

        public string MoviePageName
        {
            get
            {
                return "movies";
            }
        }

        public string TVPageName
        {
            get
            {
                return "tv shows";
            }
        }

        public string StreamPageName
        {
            get
            {
                return "stream";
            }
        }

        public string SettingsPageName
        {
            get
            {
                return "settings";
            }
        }

        public string ButtonText
        {
            get
            {
                return "Save";
            }
        }

        public string UserNameText
        {
            get
            {
                return "User name";
            }
        }

        public string PasswordText
        {
            get
            {
                return "Password";
            }
        }

        public RelayCommand ViewLoadedCommand { get; private set; }

        public RelayCommand RefreshCommand
        {
            get;
            private set;
        }

        public RelayCommand PreviousCommand
        {
            get;
            private set;
        }

        public RelayCommand NextCommand
        {
            get;
            private set;
        }

        public RelayCommand UserProfileCommand
        {
            get;
            private set;
        }

        public RelayCommand AboutCommand
        {
            get;
            private set;
        }

        public RelayCommand<int> MovieItemSelectedCommand
        {
            get;
            private set;
        }

        public RelayCommand<int> TVShowItemSelectedCommand
        {
            get;
            private set;
        }

        public RelayCommand<SelectionChangedEventArgs> SelectPivotCommand
        {
            get;
            private set;
        }
        #endregion

        #region Public bindable properties
        #region SelectedMenu
        /// <summary>
        /// The <see cref="SelectedMenu" /> property's name.
        /// </summary>
        public const string SelectedMenuPropertyName = "SelectedMenu";

        private MenuElement _selectedMenu = null;

        /// <summary>
        /// Sets and gets the SelectedMenu property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public MenuElement SelectedMenu
        {
            get
            {
                return _selectedMenu;
            }

            set
            {
                if (_selectedMenu == value)
                {
                    return;
                }

                _selectedMenu = value;
                RaisePropertyChanged(SelectedMenuPropertyName);

                if (!ReferenceEquals(_selectedMenu, null))
                {
                    switch (_selectedMenu.Name)
                    {
                        case "settings":
                            this.NavigationService.Navigate(ViewModelLocator.SettingsPageUri);
                            break;
                        case "about":
                            NavigationService.Navigate(new Uri("/YourLastAboutDialog;component/AboutPage.xaml", UriKind.Relative));
                            break;
                        default:
                            break;
                    }                   
                }
            }
        }
        #endregion

        #region MenuCollection
        /// <summary>
        /// The <see cref="MenuCollection" /> property's name.
        /// </summary>
        public const string MenuCollectionPropertyName = "MenuCollection";

        private List<MenuElement> _menuCollection = new List<MenuElement>();

        /// <summary>
        /// Sets and gets the MenuCollection property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public List<MenuElement> MenuCollection
        {
            get
            {
                return _menuCollection;
            }

            set
            {
                if (_menuCollection == value)
                {
                    return;
                }

                _menuCollection = value;
                RaisePropertyChanged(MenuCollectionPropertyName);
            }
        }
        #endregion

        #region MovieCollection
        /// <summary>
        /// The <see cref="MovieCollection" /> property's name.
        /// </summary>
        public const string MovieCollectionPropertyName = "MovieCollection";

        private List<Movie> _movieCollection = null;

        /// <summary>
        /// Gets the MovieCollection property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public List<Movie> MovieCollection
        {
            get
            {
                return _movieCollection;
            }

            set
            {
                this.SetPropertyAndNotify(ref _movieCollection, value, MovieCollectionPropertyName);
            }
        }
        #endregion

        #region TVShowCollection
        /// <summary>
        /// The <see cref="TVShowCollection" /> property's name.
        /// </summary>
        public const string TVShowCollectionPropertyName = "TVShowCollection";

        private List<TVShow> _tvShowCollection = null;

        /// <summary>
        /// Gets the TVShowCollection property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public List<TVShow> TVShowCollection
        {
            get
            {
                return _tvShowCollection;
            }

            set
            {
                this.SetPropertyAndNotify(ref _tvShowCollection, value, TVShowCollectionPropertyName);
            }
        }
        #endregion

        #region StreamCollection
        /// <summary>
        /// The <see cref="StreamCollection" /> property's name.
        /// </summary>
        public const string StreamCollectionPropertyName = "StreamCollection";

        //private List<StreamItem> _streamCollection = new List<StreamItem>();

        /// <summary>
        /// Gets the StreamCollection property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        //public List<StreamItem> StreamCollection
        //{
        //    get
        //    {
        //        return _streamCollection;
        //    }

        //    set
        //    {
        //        this.SetPropertyAndNotify(ref _streamCollection, value, StreamCollectionPropertyName);
        //    }
        //}

        private BatchObservableCollection<StreamItem> _streamCollection = new BatchObservableCollection<StreamItem>();

        public ObservableCollection<StreamItem> StreamCollection
        {
            get
            {
                return _streamCollection;
            }
            set
            {
                if (!ReferenceEquals(_streamCollection, null))
                {
                    _streamCollection.Clear();

                    if (_streamCollection != value)
                    {
                        foreach (var streamItem in value)
                        {
                            _streamCollection.Add(streamItem);
                        }
                    }
                }
                RaisePropertyChanged(StreamCollectionPropertyName);
            }
        }
        #endregion

        #region SelectedStreamItem
        /// <summary>
        /// The <see cref="SelectedStreamItem" /> property's name.
        /// </summary>
        public const string SelectedStreamItemPropertyName = "SelectedStreamItem";

        private StreamItem _selectedStreamItem = null;

        /// <summary>
        /// Gets the SelectedStreamItem property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public StreamItem SelectedStreamItem
        {
            get
            {
                return _selectedStreamItem;
            }

            set
            {
                this.SetPropertyAndNotify(ref _selectedStreamItem, value, SelectedStreamItemPropertyName);
                if (!ReferenceEquals(_selectedStreamItem, null))
                {
                    this.MessengerInstance.Send<SelectedFriendChangedMessage>(new SelectedFriendChangedMessage(_selectedStreamItem.Friend.UserName));
                    NavigationService.Navigate(ViewModelLocator.CollectionPageUri);
                }
            }
        }
        #endregion

        #region ProgressIndicatorVisible
        /// <summary>
        /// The <see cref="ProgressIndicatorVisible" /> property's name.
        /// </summary>
        public const string ProgressIndicatorVisiblePropertyName = "ProgressIndicatorVisible";

        private bool _progressIndicatorVisible = false;

        /// <summary>
        /// Gets the ProgressIndicatorVisible property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool ProgressIndicatorVisible
        {
            get
            {
                return _progressIndicatorVisible;
            }

            set
            {
                this.SetPropertyAndNotify(ref _progressIndicatorVisible, value, ProgressIndicatorVisiblePropertyName);
            }
        }
        #endregion

        #region CollectionVisible
        /// <summary>
        /// The <see cref="CollectionVisible" /> property's name.
        /// </summary>
        public const string CollectionVisiblePropertyName = "CollectionVisible";

        private Visibility _collectionVisible = Visibility.Collapsed;

        /// <summary>
        /// Gets the CollectionVisible property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public Visibility CollectionVisible
        {
            get
            {
                return _collectionVisible;
            }

            set
            {
                this.SetPropertyAndNotify(ref _collectionVisible, value, CollectionVisiblePropertyName);
            }
        }
        #endregion

        #region AppBarVisible
        public const string AppBarVisiblePropertyName = "AppBarVisible";

        private bool _appBarVisible = false;
        public bool AppBarVisible
        {
            get
            {
                return _appBarVisible;
            }
            set
            {
                if (Equals(_appBarVisible, value))
                {
                    return;
                }
                _appBarVisible = value;
                RaisePropertyChanged(AppBarVisiblePropertyName);
            }
        }
        #endregion

        #region PagingAppBarVisible
        /// <summary>
        /// The <see cref="PagingAppBarVisible" /> property's name.
        /// </summary>
        public const string PagingAppBarVisiblePropertyName = "PagingAppBarVisible";

        private bool _pagingAppBarVisible = false;

        /// <summary>
        /// Gets the PagingAppBarVisible property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool PagingAppBarVisible
        {
            get
            {
                return _pagingAppBarVisible;
            }

            set
            {
                this.SetPropertyAndNotify(ref _pagingAppBarVisible, value, PagingAppBarVisiblePropertyName);
            }
        }
        #endregion

        #region SelectedFriend
        /// <summary>
        /// The <see cref="SelectedFriend" /> property's name.
        /// </summary>
        public const string SelectedFriendPropertyName = "SelectedFriend";

        private string _selectedFriend = string.Empty;

        /// <summary>
        /// Gets the SelectedFriend property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public string SelectedFriend
        {
            get
            {
                return string.IsNullOrEmpty(_selectedFriend) ? FollwItApi.GetInstance().UserName : _selectedFriend;
            }

            set
            {
                this.SetPropertyAndNotify(ref _selectedFriend, value, SelectedFriendPropertyName);
                RaisePropertyChanged(ApplicationTitlePropertyName);
            }
        }
        #endregion

        #region ApplicationTitle
        /// <summary>
        /// The <see cref="ApplicationTitle" /> property's name.
        /// </summary>
        public const string ApplicationTitlePropertyName = "ApplicationTitle";

        private string _applicationTitle = string.Empty;

        /// <summary>
        /// Gets the ApplicationTitle property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public string ApplicationTitle
        {
            get
            {
                //Use of the Coding 4 FUn PhoneHelper to get the application title from the configuration
                string selectedFriend = string.IsNullOrEmpty(this.SelectedFriend) ? string.Empty : this.SelectedFriend.ToUpper();
                return string.Concat(PhoneHelper.GetAppAttribute("Title").ToUpper(), " ", selectedFriend);
            }
        }
        #endregion

        #region UserName
        /// <summary>
        /// The <see cref="UserName" /> property's name.
        /// </summary>
        public const string UserNamePropertyName = "UserName";

        private string _userName = string.Empty;

        /// <summary>
        /// Gets the UserName property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public string UserName
        {
            get
            {
                return _userName;
            }

            set
            {
                this.SetPropertyAndNotify(ref _userName, value, UserNamePropertyName);
                this.SelectedFriend = _userName;
            }
        }
        #endregion

        #region Password
        /// <summary>
        /// The <see cref="Password" /> property's name.
        /// </summary>
        public const string PasswordPropertyName = "Password";

        private string _password = string.Empty;

        /// <summary>
        /// Gets the Password property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public string Password
        {
            get
            {
                return _password;
            }

            set
            {
                this.SetPropertyAndNotify(ref _password, value, PasswordPropertyName);
            }
        }
        #endregion

        #region ViewLoadedCommandEnabled
        /// <summary>
        /// The <see cref="ViewLoadedCommandEnabled" /> property's name.
        /// </summary>
        public const string ViewLoadedCommandEnabledPropertyName = "ViewLoadedCommandEnabled";

        private bool _viewLoadedCommandEnabled = true;

        /// <summary>
        /// Gets the ViewLoadedCommandEnabled property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool ViewLoadedCommandEnabled
        {
            get
            {
                return _viewLoadedCommandEnabled;
            }

            set
            {
                this.SetPropertyAndNotify(ref _viewLoadedCommandEnabled, value, ViewLoadedCommandEnabledPropertyName);
            }
        }
        #endregion

        #region IsStreamLoaded
        /// <summary>
        /// The <see cref="IsStreamLoaded" /> property's name.
        /// </summary>
        public const string IsStreamLoadedPropertyName = "IsStreamLoaded";

        private bool _isStreamLoaded = false;

        /// <summary>
        /// Gets the IsStreamLoaded property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool IsStreamLoaded
        {
            get
            {
                return _isStreamLoaded;
            }

            set
            {
                this.SetPropertyAndNotify(ref _isStreamLoaded, value, IsStreamLoadedPropertyName);
            }
        }
        #endregion

        #region IsMovieCollectionLoaded
        /// <summary>
        /// The <see cref="IsMovieCollectionLoaded" /> property's name.
        /// </summary>
        public const string IsMovieCollectionLoadedPropertyName = "IsMovieCollectionLoaded";

        private bool _isMovieCollectionLoaded = false;

        /// <summary>
        /// Gets the IsMovieCollectionLoaded property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool IsMovieCollectionLoaded
        {
            get
            {
                return _isMovieCollectionLoaded;
            }

            set
            {
                this.SetPropertyAndNotify(ref _isMovieCollectionLoaded, value, IsMovieCollectionLoadedPropertyName);
            }
        }
        #endregion

        #region IsTVShowCollectionLoaded
        /// <summary>
        /// The <see cref="IsTVShowCollectionLoaded" /> property's name.
        /// </summary>
        public const string IsTVShowCollectionLoadedPropertyName = "IsTVShowCollectionLoaded";

        private bool _isTVShowCollectionLoaded = false;

        /// <summary>
        /// Gets the IsTVShowCollectionLoaded property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool IsTVShowCollectionLoaded
        {
            get
            {
                return _isTVShowCollectionLoaded;
            }

            set
            {
                this.SetPropertyAndNotify(ref _isTVShowCollectionLoaded, value, IsTVShowCollectionLoadedPropertyName);
            }
        }
        #endregion
        #endregion

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel(INavigationService navigationService, IStorageService storageService, IStoreSettings settingsService, IMessenger messenger)
            : base(navigationService, storageService, settingsService, messenger)
        {
            #region Command setup
            this.RefreshCommand = new RelayCommand(() => this.Refresh()); 
            this.PreviousCommand = new RelayCommand(() => this.Load(false, PageMode.Previous));
            this.NextCommand = new RelayCommand(() => this.Load(false, PageMode.Next));
            this.UserProfileCommand = new RelayCommand(() => navigationService.Navigate(ViewModelLocator.UserProfilePageUri));
            this.MovieItemSelectedCommand = new RelayCommand<int>((movieID) => this.ItemSelected(movieID, SelectedItem.Movie));
            this.TVShowItemSelectedCommand = new RelayCommand<int>((tvShowID) => this.ItemSelected(tvShowID, SelectedItem.TVShow));

            this.ViewLoadedCommand = new RelayCommand(() =>
                {
                    if (!string.IsNullOrEmpty(FollwItApi.GetInstance().UserName) && !string.IsNullOrEmpty(FollwItApi.GetInstance().Password))
                        this.AppBarVisible = true;
                    this.ViewLoadedCommandEnabled = false;
                }
            );

            this.SelectPivotCommand = new RelayCommand<SelectionChangedEventArgs>((args) => {
                _currentPivot = Enum<PivotName>.Parse(((PivotItem)args.AddedItems[0]).Name);
                switch (_currentPivot)
                {
                    case PivotName.MoviePivotItem:
                        this.AppBarVisible = true;
                        this.PagingAppBarVisible = true;
                        break;
                    case PivotName.TVShowPivotItem:
                        this.AppBarVisible = true;
                        this.PagingAppBarVisible = true;
                        break;
                    case PivotName.StreamPivotItem:
                        this.AppBarVisible = true;
                        this.PagingAppBarVisible = false;
                        //this.LoadStream();
                        break;
                    case PivotName.MenuPivotItem:
                        this.AppBarVisible = false;
                        break;
                    default:
                        break;
                }
            });

            this.AboutCommand = new RelayCommand(() => NavigationService.Navigate(new Uri("/YourLastAboutDialog;component/AboutPage.xaml", UriKind.Relative)));
            #endregion

            this.MessengerInstance.Register<NotificationMessage>(this, action =>
                            {
                                switch (action.Notification)
                                {
                                    case "AuthenticateComplete":
                                        this.Load(true);
                                        break;
                                    default:
                                        break;
                                }
                            }
                            );

            this.MenuCollection.Add(new MenuElement() { Name = "settings" });
            this.MenuCollection.Add(new MenuElement() { Name = "about" });

            //Look for property changes, so we can correctly adjust the ProgressIndicator
            this.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(MainViewModel_PropertyChanged);

            string userName;
            if (this.SettingsService.TryToRead<string>("Follwit.UserName", out userName))
            {
                FollwItApi.GetInstance().UserName = userName;
                this.UserName = userName;
            }

            string password;
            if (this.SettingsService.TryToRead<string>("Follwit.Password", out password))
            {
                FollwItApi.GetInstance().Password = password;
                this.Password = password;
            }

            if (!string.IsNullOrEmpty(FollwItApi.GetInstance().UserName) && !string.IsNullOrEmpty(FollwItApi.GetInstance().Password))
                this.Load(true);
        }
        #endregion

        #region Private methods
        private void MainViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == IsMovieCollectionLoadedPropertyName || e.PropertyName == IsTVShowCollectionLoadedPropertyName || e.PropertyName == IsStreamLoadedPropertyName)
            {
                //If all collections are loaded we disable the progress indicator
                if (this.IsMovieCollectionLoaded && this.IsTVShowCollectionLoaded && this.IsStreamLoaded)
                    this.ProgressIndicatorVisible = false;
            }
        }

        private void Load(bool triggerCollectionVisibility, PageMode pageMode = PageMode.First)
        {
            if (string.IsNullOrEmpty(FollwItApi.GetInstance().UserName) || string.IsNullOrEmpty(FollwItApi.GetInstance().Password))
            {
                MessageBoxResult result =
                    MessageBox.Show(
                        "No user information found!" + Environment.NewLine + "Please provide it on the Settings page...",
                        "Info required", MessageBoxButton.OK);
            }
            else
            {
                this.ProgressIndicatorVisible = true;

                this.LoadStream();

                if (triggerCollectionVisibility)
                    this.CollectionVisible = Visibility.Collapsed;                

                this.LoadMovies(triggerCollectionVisibility, pageMode);
                this.LoadSeries(triggerCollectionVisibility, pageMode);
            }
        }

        private void LoadSeries(bool triggerCollectionVisibility, PageMode pageMode)
        {
            this.IsTVShowCollectionLoaded = false;
            DataManager.Current.Load<agfxTVShowCollectionViewModel>(this.SelectedFriend, (vm) =>
            {
                _tvShowCollectionVM = vm;
                switch (pageMode)
                {
                    case PageMode.First:
                        this.TVShowCollection = (from tvShow in _tvShowCollectionVM.TVShows
                                                 select tvShow).Take(_pageSize).ToList();
                        _currentPageTVShow = 0;
                        break;
                    case PageMode.Previous:
                        if (_currentPivot == PivotName.TVShowPivotItem)
                        {
                            if (_currentPageTVShow == 0)
                                this.TVShowCollection = (from tvShow in _tvShowCollectionVM.TVShows
                                                         select tvShow).Take(_pageSize).ToList();
                            else
                            {
                                _currentPageTVShow = --_currentPageTVShow;
                                this.TVShowCollection = (from tvShow in _tvShowCollectionVM.TVShows
                                                         select tvShow).Skip(_pageSize * _currentPageTVShow).Take(_pageSize).ToList();
                            }
                        }
                        break;
                    case PageMode.Next:
                        if (_currentPivot == PivotName.TVShowPivotItem)
                        {
                            _currentPageTVShow = ++_currentPageTVShow;
                            if ((_pageSize * _currentPageTVShow) > _tvShowCollectionVM.TVShows.Count)
                                _currentPageTVShow = --_currentPageTVShow;
                            else
                                this.TVShowCollection = (from tvShow in _tvShowCollectionVM.TVShows
                                                         select tvShow).Skip(_pageSize * _currentPageTVShow).Take(_pageSize).ToList();
                        }
                        break;
                    default:
                        break;
                }

                this.IsTVShowCollectionLoaded = true;
                if (triggerCollectionVisibility)
                    this.CollectionVisible = Visibility.Visible;
            },
                (ex) =>
                {
                    this.IsTVShowCollectionLoaded = true;
                    throw new FollwitException("Error while loading TVShow Collection", ex);
                });
        }

        private void LoadMovies(bool triggerCollectionVisibility, PageMode pageMode)
        {
            this.IsMovieCollectionLoaded = false;
            DataManager.Current.Load<agfxMovieCollectionViewModel>(this.SelectedFriend, (vm) =>
            {
                _movieCollectionVM = vm;

                switch (pageMode)
                {
                    case PageMode.First:
                        this.MovieCollection = (from movie in _movieCollectionVM.Movies
                                                select movie).Take(_pageSize).ToList();
                        _currentPageMovie = 0;
                        break;
                    case PageMode.Previous:
                        if (_currentPivot == PivotName.MoviePivotItem)
                        {
                            if (_currentPageMovie == 0)
                                this.MovieCollection = (from movie in _movieCollectionVM.Movies
                                                        select movie).Take(_pageSize).ToList();
                            else
                            {
                                _currentPageMovie = --_currentPageMovie;
                                this.MovieCollection = (from movie in _movieCollectionVM.Movies
                                                        select movie).Skip(_pageSize * _currentPageMovie).Take(_pageSize).ToList();
                            }
                        }
                        break;
                    case PageMode.Next:
                        if (_currentPivot == PivotName.MoviePivotItem)
                        {
                            _currentPageMovie = ++_currentPageMovie;
                            if ((_pageSize * _currentPageMovie) > _movieCollectionVM.Movies.Count)
                                _currentPageMovie = --_currentPageMovie;
                            else
                                this.MovieCollection = (from movie in _movieCollectionVM.Movies
                                                        select movie).Skip(_pageSize * _currentPageMovie).Take(_pageSize).ToList();
                        }
                        break;
                    default:
                        break;
                }

                this.IsMovieCollectionLoaded = true;
                if (triggerCollectionVisibility)
                    this.CollectionVisible = Visibility.Visible;
            },
                (ex) =>
                {
                    this.IsMovieCollectionLoaded = true;
                    throw new FollwitException("Error while loading Movie Collection", ex);
                });
        }

        private void LoadStream()
        {
            _streamCollection.Clear();
            this.IsStreamLoaded = false;
            DataManager.Current.Load<agfxFriendsViewModel>(FollwItApi.GetInstance().UserName, (vm) =>
            {
                var friends = vm.Friends;
                _friendsCount = friends.Count;
                foreach (Friend friend in friends)
                {                    
                    DataManager.Current.Load<agfxStreamViewModel>(friend, (streamvm) =>
                        {
                            if (!streamvm.Stream.IsNull)
                                _streamCollection.Add(streamvm.Stream);

                            this.SignalCollection();
                        },
                        (ex) =>
                        {
                            this.IsStreamLoaded = true;
                            throw new FollwitException("Error while loading Stream", ex);
                        }
                        );
                }
            },
            (ex) =>
            {
                this.IsStreamLoaded = true;
                throw new FollwitException("Error while loading Friends", ex);
            });            
        }

        private void SignalCollection()
        {
            --_friendsCount;
            if (_friendsCount == 0)
            {
                this.IsStreamLoaded = true;
                RaisePropertyChanged(StreamCollectionPropertyName);
            }
        }

        private void Refresh()
        {
            if (string.IsNullOrEmpty(FollwItApi.GetInstance().UserName) || string.IsNullOrEmpty(FollwItApi.GetInstance().Password))
            {
                MessageBoxResult result = MessageBox.Show("No user information found!" + Environment.NewLine + "Please provide it on the Settings page...", "Info required", MessageBoxButton.OK);
            }
            else
            {
                this.ProgressIndicatorVisible = true;
                this.IsMovieCollectionLoaded = false;
                this.IsTVShowCollectionLoaded = false;

                _streamCollection.Clear();
                this.IsStreamLoaded = false;
                DataManager.Current.Refresh<agfxFriendsViewModel>(FollwItApi.GetInstance().UserName, (vm) =>
                {
                    var friends = vm.Friends;
                    _friendsCount = friends.Count;
                    foreach (Friend friend in friends)
                    {
                        DataManager.Current.Refresh<agfxStreamViewModel>(friend, (streamvm) =>
                        {
                            if (!streamvm.Stream.IsNull)
                                _streamCollection.Add(streamvm.Stream);

                            this.SignalCollection();
                        },
                            (ex) =>
                            {
                                this.IsStreamLoaded = true;
                                throw new FollwitException("Error while refreshing Stream", ex);
                            }
                            );
                    }
                },
                (ex) =>
                {
                    this.IsStreamLoaded = true;
                    throw new FollwitException("Error while refreshing Friends", ex);
                });

                DataManager.Current.Refresh<agfxMovieCollectionViewModel>(this.SelectedFriend, (vm) =>
                {
                    _movieCollectionVM = vm;
                    this.MovieCollection = (from movie in _movieCollectionVM.Movies
                                            select movie).Take(_pageSize).ToList();
                    _currentPageMovie = 0;
                    this.IsMovieCollectionLoaded = true;
                    this.CollectionVisible = Visibility.Visible;
                },
                    (ex) =>
                    {
                        this.IsMovieCollectionLoaded = true;
                        throw new FollwitException("Error while refreshing Movie Collection", ex);
                    });

                DataManager.Current.Refresh<agfxTVShowCollectionViewModel>(this.SelectedFriend, (vm) =>
                {
                    _tvShowCollectionVM = vm;
                    this.TVShowCollection = (from tvShow in _tvShowCollectionVM.TVShows
                                             select tvShow).Take(_pageSize).ToList();
                    _currentPageTVShow = 0;
                    this.IsTVShowCollectionLoaded = true;
                    this.CollectionVisible = Visibility.Visible;
                },
                    (ex) =>
                    {
                        this.IsTVShowCollectionLoaded = true;
                        throw new FollwitException("Error while refreshing TVShow Collection", ex);
                    });
            }
        }

        private void ItemSelected(int itemID, SelectedItem type)
        {
            switch (type)
            {
                case SelectedItem.Movie:
                    NavigationService.Navigate(ViewModelLocator.MovieSummaryPageUri);
                    this.MessengerInstance.Send<SelectedMovieChangedMessage>(new SelectedMovieChangedMessage(itemID));
                    break;
                case SelectedItem.TVShow:
                    NavigationService.Navigate(ViewModelLocator.TVShowSummaryPageUri);
                    this.MessengerInstance.Send<SelectedTVShowChangedMessage>(new SelectedTVShowChangedMessage(itemID));
                    break;
                default:
                    break;
            }
        }
        #endregion

        #region ViewModelBaseWp7 implementation
        protected override void IsBeingActivated(WP7Contrib.Services.Storage.IStorage storage)
        {
            this.UserName = storage.Read<string>("Follwit.UserName");
            this.Password = storage.Read<string>("Follwit.Password");
        }

        protected override void IsBeingDeactivated(WP7Contrib.Services.Storage.IStorage storage)
        {
            storage.Write<string>("Follwit.UserName", this.UserName);
            storage.Write<string>("Follwit.Password", this.Password);
        }
        #endregion        
    }
}
